package com.ruoyi.framework.aop;

import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 实现读写分离
 */
@Aspect
@Component
@Order(0)//配置注解优先级，优于事物注解@Transactional先进行数据源切换，不然在事物中进行数据源切换无效
public class DataSourceAop {

    @Value("${spring.datasource.druid.slave.enabled}")
    private boolean enabled;

    @Pointcut("!@annotation(com.ruoyi.common.annotation.DataSource) " +
      "&& (execution(* com.ruoyi..*.service..*.select*(..)) " +
      "|| execution(* com.ruoyi..*.service..*.get*(..)) " +
      "|| execution(* com.ruoyi..*.service..*.query*(..)))")
    public void readPointcut() {
    }


    @Pointcut("!@annotation(com.ruoyi.common.annotation.DataSource) " +
             "&&(execution(* com.ruoyi..*.service..*.insert*(..)) " +
             "|| execution(* com.ruoyi..*.service..*.add*(..)) " +
             "|| execution(* com.ruoyi..*.service..*.update*(..)) " +
             "|| execution(* com.ruoyi..*.service..*.edit*(..)) " +
             "|| execution(* com.ruoyi..*.service..*.delete*(..)) " +
             "|| execution(* com.ruoyi..*.service..*.remove*(..)))")
    public void writePointcut() {
    }

    @Before("readPointcut()")
    public void read() {
        if (enabled) {
            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
        }
    }

    @Before("writePointcut()")
    public void write() {
        if (enabled) {
            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
        }
    }

    @After("readPointcut()")
    public void clearRead() {
        if (enabled) {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }

    @After("writePointcut()")
    public void clearWrite() {
        if (enabled) {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }
}
